using System;
using System.Web;
using log4net;
using NHibernate;
using NHibernate.Cfg;
namespace DailyReport.Core.Util
{
    public class TransactionManager
    {
        ITransaction transaction;


        internal TransactionManager(ITransaction transaction)
        {
            this.transaction = transaction;
        }

        internal ITransaction Transaction
        {
            set { transaction = value; }
        }
        
        public void Commit()
        {
         transaction.Commit();   
        }
        public void RollBack()
        {
            transaction.Rollback();
        }
    }
    public class ConnectionManager
    {
        
        ISessionFactory sessionFactory;
        ISession session;
        private static ILog log = LogManager.GetLogger("ConnectionManager");
        private static readonly string KEY_NHIBERNATE_FACTORY = "NHibernateSessionFactory";
        private static readonly string KEY_NHIBERNATE_SESSION = "NHibernateSession";

        static ConnectionManager instance;
        
        
        
        public TransactionManager BeginTransaction()
        {
            return new TransactionManager(Session.BeginTransaction());
        }

        private ISessionFactory CreateSessionFactory()
        {
            Configuration config;
            ISessionFactory factory;

            config = new Configuration();

            if (config == null)
                throw new InvalidOperationException("NHibernate configuration is null.");

            config.Configure();

            factory = config.BuildSessionFactory();

            if (factory == null)
                throw new InvalidOperationException("Call to Configuration.BuildSessionFactory() returned null.");
            else
                return factory;
        }

        internal static void initialize()
        {
            if (HttpContext.Current == null)
            {
                Instance.sessionFactory = Instance.CreateSessionFactory();
            }else
            {
                HttpContext.Current.Application[KEY_NHIBERNATE_FACTORY] = Instance.CreateSessionFactory();
            }
        }


        public static ConnectionManager Instance
        {
            get
            {
                //log.Debug("Instance-->");
                if (instance == null)
                    instance = new ConnectionManager();

                //log.Debug("Instance-->" + instance);
                return instance;
            }
        }

        public ISessionFactory CurrentFactory
        {
            get
            {
                if (HttpContext.Current == null)
                {
                    // running without an HttpContext (non-web mode)
                    // the nhibernate session is a singleton in the app domain
                    if (sessionFactory != null)
                        return sessionFactory;
                    else
                    {
                        sessionFactory = CreateSessionFactory();
                        return sessionFactory;
                    }
                }
                else
                {
                    // running inside of an HttpContext (web mode)
                    // the nhibernate session is a singleton to the http request
                    HttpContext currentContext = HttpContext.Current;
                    ISessionFactory factory = currentContext.Application[KEY_NHIBERNATE_FACTORY] as ISessionFactory;
                    //log.Debug("Is Webapp...");
                    if (factory == null)
                    {
                        factory = CreateSessionFactory();
                        currentContext.Application[KEY_NHIBERNATE_FACTORY] = factory;
                    }
                    //log.Debug("Factory:"+factory);
                    return factory;
                }
            }
        }

        private ISession CreateSession()
        {
            ISessionFactory factory;
            ISession session1;

            factory = CurrentFactory;

            if (factory == null)
            {
                throw new InvalidOperationException("Call to Configuration.BuildSessionFactory() returned null.");
            }

            session1 = factory.OpenSession();

            if (session1 == null)
            {
                throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
            }
            //log.Debug("CreateSesion:"+session1);
            return session1;
        }

        public ISession Session
        {
            get
            {

                if (HttpContext.Current == null)
                {
                    // running without an HttpContext (non-web mode)
                    // the nhibernate session is a singleton in the app domain
                    if (session != null)
                    {
                        return session;
                    }
                    else
                    {
                        session = CreateSession();

                        return session;
                    }
                }
                else
                {
                    // running inside of an HttpContext (web mode)
                    // the nhibernate session is a singleton to the http request
                    HttpContext currentContext = HttpContext.Current;
                    //log.Debug("SESSION:-->WebApplication");
                    session = currentContext.Items[KEY_NHIBERNATE_SESSION] as ISession;
                    
                    if (session == null)
                    {
                        log.Debug("Return Creating session");
                        session = CreateSession();
                        currentContext.Items[KEY_NHIBERNATE_SESSION] = session;
                    }else
                        log.Debug("Return current session");
                    //log.Debug("Final SEssion");
                    return session;
                }
            }
        }


        public void StartSession(object sender)
        {
            HttpApplication application = (HttpApplication)sender;
            HttpContext context = application.Context;

            context.Items[KEY_NHIBERNATE_SESSION] = CreateSession();

        }
        
        public void EndSession(object sender)
        {
            HttpApplication application = (HttpApplication)sender;
            HttpContext context = application.Context;

            ISession sessionToClose = context.Items[KEY_NHIBERNATE_SESSION] as ISession;
            if (sessionToClose != null)
            {
                try
                {
                    sessionToClose.Flush();
                    sessionToClose.Close();
                }
                catch { }
            }

            context.Items[KEY_NHIBERNATE_SESSION] = null;

        }
        
    }
}
